package com.example.demo.model;

import com.example.demo.constant.Constants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;

import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
public class OnlineUserManager {
    //类似于游戏大厅,通过哈希表中是否还存在用户id来判断是否在线
    //如果通过用户id没找到对应的哈希值,就证明用户下线了

    //如果使用我们的HashMap可能会造成线程安全问题
    //当多个线程同时执行put操作时，若两个不同的键哈希到同一桶且该位置为空，两个线程可能同时将节点插入该位置，导致其中一个线程的数据被覆盖。
    //所以我们使用ConcurrentHashMap来存储,因为ConcurrentHashMap是线程安全的
    //ConcurrentHashMap给每个哈系统都进行加锁,在哈希表(数据结构)中产生锁冲突的概率不大,所以也不会怎么消耗资源
    private ConcurrentHashMap<Integer, WebSocketSession> gameHall=new ConcurrentHashMap<>();




    /**
     * 如果当前用户登录成功后,在登录页面的session就会被WebSocket拿到自己的session中
     * registry.addHandler(matchController,"/findMatch").addInterceptors(new HttpSessionHandshakeInterceptor());
     * 拿到之后将session和当前用户的userId存储到哈希表中
     * 通过userId来扫描哈希表,如果当前用户id对应的value有值,就证明当前用户在线
     * @param userId 用户Id作为键存储到哈希表中
     * @param session http登录后获取的session,WebSocket将http的session拿到自己的session里
     */

    public void enterGameHall(Integer userId,WebSocketSession session){
        gameHall.put(userId,session);
        log.info("当前上线的用户为",session.getAttributes().get(Constants.USER_SESSION_KEY));

    }

    /**
     * 如果客户端和服务器断开连接之后,调用这个方法将用户在哈希中删除,就证明该用户下线了
     * @param userId 用户id
     */
    public void exitGameHall(Integer userId){
        gameHall.remove(userId);
    }


    public WebSocketSession getFromGameHall(Integer userId){
        WebSocketSession webSocketSession = gameHall.get(userId);
        return webSocketSession;
    }





    /**
     * 因为上面的是校验用户在登录大厅是否在线,当玩家进入游戏房间之后
     * 就会离开大厅页面,在大厅页面视为下线了
     * 所以我们还要定义一个在房间中让用户上线
     */
    private ConcurrentHashMap<Integer,WebSocketSession> gameRoom=new ConcurrentHashMap<>();
    public void enterGameRoom(Integer userId,WebSocketSession session){
        gameRoom.put(userId,session);
        log.info("当前上线的用户为",session.getAttributes().get(Constants.USER_SESSION_KEY));

    }
    public void exitRoom(Integer userId){
        gameRoom.remove(userId);
    }

    public WebSocketSession getFromRoom(Integer userId){
        WebSocketSession webSocketSession = gameRoom.get(userId);
        return webSocketSession;
    }
}
